{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "711a3001",
   "metadata": {
    "vscode": {
     "languageId": "polyglot-notebook"
    }
   },
   "source": [
    "1. 程序集: 经编译器编译得到的,供进一步编译执行的中间产物,在Windows系统中,它一般表现的后缀是.dll(库文件),或者exe文件\n",
    "2. 元数据: 用来描述数据的数据,有关程序以及类型的数据被称为元数据,他们保存在程序集中\n",
    "3. 反射: 程序在运行时可以查看其他程序集或者自己的元数据(可以得到自己程序集代码的何种信息)\n",
    "4. 反射的作用: 程序运行时得到所有的元数据; 程序运行中实例化对象, 程序运行时创建新的对象, 用这些对象执行任务(一个程序中使用另一个程序中的代码)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "7525f181",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "class ReflectExample\n",
    "{\n",
    "    private string message = \"Hello from ReflectExample!\";\n",
    "    public void DisplayMessage()\n",
    "    {\n",
    "        Console.WriteLine(\"Id: {0}, Message: {1}\", this.testId, this.message);\n",
    "    }\n",
    "\n",
    "    public int testId = 0;\n",
    "\n",
    "    public ReflectExample()\n",
    "    {\n",
    "        this.testId = 0;\n",
    "        this.message=\"Hello from ReflectExample!\";\n",
    "    }\n",
    "\n",
    "    public ReflectExample(int id)\n",
    "    {\n",
    "        this.testId = id;\n",
    "    }\n",
    "\n",
    "    public ReflectExample(int id, string message):this(id)\n",
    "    {\n",
    "        this.message = message;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ae0fe40",
   "metadata": {},
   "source": [
    "1. Type类: 类的成员变量,成员函数等信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "7735b412",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "System.Int32\n",
      "System.Int32\n",
      "System.Int32\n",
      "System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e\n",
      "===========================================\n",
      "Void DisplayMessage()\n",
      "System.Type GetType()\n",
      "System.String ToString()\n",
      "Boolean Equals(System.Object)\n",
      "Int32 GetHashCode()\n",
      "Void .ctor()\n",
      "Void .ctor(Int32)\n",
      "Void .ctor(Int32, System.String)\n",
      "Int32 testId\n",
      "===========================================\n",
      "Void .ctor()\n",
      "Void .ctor(Int32)\n",
      "Void .ctor(Int32, System.String)\n",
      "Id: 0, Message: Hello from ReflectExample!\n",
      "Id: 42, Message: Hello, Reflection!\n",
      "===========================================\n",
      "Int32 testId\n",
      "Int32 testId\n",
      "42\n",
      "100\n",
      "===========================================\n",
      "Void DisplayMessage()\n",
      "System.Type GetType()\n",
      "System.String ToString()\n",
      "Boolean Equals(System.Object)\n",
      "Int32 GetHashCode()\n",
      "Void DisplayMessage()\n",
      "Id: 100, Message: Hello, Reflection!\n"
     ]
    }
   ],
   "source": [
    "using System.Reflection;\n",
    "// Type类(类的信息类) 它是反射功能的基础 它时访问元数据的主要方式. 使用type成员获取有关类型声明的信息\n",
    "int number = 10;\n",
    "Type type = number.GetType();\n",
    "Console.WriteLine(type);\n",
    "Console.WriteLine(typeof(int));\n",
    "Console.WriteLine(Type.GetType(\"System.Int32\")); //类名必须包含命名空间\n",
    "//得到类的程序集信息\n",
    "Console.WriteLine(type.Assembly);\n",
    "Console.WriteLine(\"===========================================\");\n",
    "\n",
    "//获取类的所有公共成员\n",
    "Type typeExample = typeof(ReflectExample);\n",
    "MemberInfo[] members = typeExample.GetMembers();\n",
    "foreach (MemberInfo member in members)\n",
    "{\n",
    "    Console.WriteLine(member);\n",
    "}\n",
    "\n",
    "Console.WriteLine(\"===========================================\");\n",
    "//获取类的公共构造函数并调用\n",
    "ConstructorInfo[] constructors = typeExample.GetConstructors();\n",
    "foreach (ConstructorInfo constructor in constructors)\n",
    "{\n",
    "    Console.WriteLine(constructor);\n",
    "}\n",
    "//获取其中一个构造函数并执行,得到构造函数需要传入Type数组, 数组中的内容按顺序是参数类型\n",
    "ConstructorInfo constructor = typeExample.GetConstructor(new Type[0]);\n",
    "ReflectExample example = constructor.Invoke(null) as ReflectExample; //调用无参构造函数,没有参数写null\n",
    "example.DisplayMessage();\n",
    "\n",
    "//获取有参构造函数\n",
    "constructor = typeExample.GetConstructor(new Type[] { typeof(int), typeof(string) });\n",
    "example = constructor.Invoke(new object[] { 42, \"Hello, Reflection!\" }) as ReflectExample; //调用有参构造函数\n",
    "example.DisplayMessage();\n",
    "\n",
    "Console.WriteLine(\"===========================================\");\n",
    "\n",
    "//获取类的所有公共成员变量\n",
    "FieldInfo[] fields = typeExample.GetFields();\n",
    "foreach (FieldInfo field in fields)\n",
    "{\n",
    "    Console.WriteLine(field);\n",
    "}\n",
    "\n",
    "//获取指定名称的成员变量\n",
    "FieldInfo fieldInfo = typeExample.GetField(\"testId\");\n",
    "if (fieldInfo != null)\n",
    "{\n",
    "    Console.WriteLine(fieldInfo);\n",
    "} \n",
    "\n",
    "//通过反射获取和设置对象的值\n",
    "Console.WriteLine(fieldInfo.GetValue(example));\n",
    "fieldInfo.SetValue(example, 100);\n",
    "Console.WriteLine(fieldInfo.GetValue(example));\n",
    "\n",
    "Console.WriteLine(\"===========================================\");\n",
    "\n",
    "//获取类的所有公共方法\n",
    "MethodInfo[] methods = typeExample.GetMethods();\n",
    "foreach (MethodInfo method in methods)\n",
    "{\n",
    "    Console.WriteLine(method);\n",
    "}\n",
    "\n",
    "//获取类的特定的方法,重载函数需要第二个参数传入Type类型,没有重载则直接使用这个函数即可\n",
    "MethodInfo specificMethod = typeExample.GetMethod(\"DisplayMessage\", new Type[0]);\n",
    "if (specificMethod != null)\n",
    "{\n",
    "    Console.WriteLine(specificMethod);\n",
    "}\n",
    "\n",
    "//调用特定的方法,传入类,和需要的参数, 参数传递为new object[] { }\n",
    "//静态方法Invoke时第一个参数为null,实例方法则传入实例对象\n",
    "specificMethod.Invoke(example, null); //无参数调用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8b187ff",
   "metadata": {},
   "source": [
    "2. Activator类 用于快速实例化对象的类,将Type对象快速实例化为对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*\n",
      "99\n",
      "100 HelloWorld\n"
     ]
    }
   ],
   "source": [
    "// 先得到type 然后快速实例化一个对象\n",
    "\n",
    "class Test {\n",
    "    public int i = 0;\n",
    "    public string str = \"*\"; \n",
    "    public Test () {\n",
    "        \n",
    "    }\n",
    "    public Test (int i) {\n",
    "        this.i = i;\n",
    "    }\n",
    "    public Test (int i, string str):this(i) {\n",
    "        this.str = str;\n",
    "    }\n",
    "}\n",
    "\n",
    "Type test = typeof(Test);\n",
    "//无参构造\n",
    "Test testobj = Activator.CreateInstance(test) as Test; //默认使用默认构造函数\n",
    "Console.WriteLine(testobj.str);\n",
    "//有参构造\n",
    "testobj = Activator.CreateInstance(test,99) as Test; //调用只有一个参数的构造函数\n",
    "Console.WriteLine(testobj.i);\n",
    "testobj = Activator.CreateInstance(test,100,\"HelloWorld\") as Test;\n",
    "Console.WriteLine(testobj.i + \" \" + testobj.str);"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aafab5b6",
   "metadata": {},
   "source": [
    "3. Assembly类:主要用于加载其他程序集,加载后才能使用Type来使用其他程序集中的信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "System.BadImageFormatException: Bad IL format. The format of the file 'D:\\CSharpCode\\21.反射\\test.dll' is invalid.\r\n   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)\r\n   at System.Reflection.Assembly.LoadFrom(String assemblyFile)\r\n   at Submission#26.<<Initialize>>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)",
     "output_type": "error",
     "traceback": [
      "System.BadImageFormatException: Bad IL format. The format of the file 'D:\\CSharpCode\\21.反射\\test.dll' is invalid.\r\n",
      "   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)\r\n",
      "   at System.Reflection.Assembly.LoadFrom(String assemblyFile)\r\n",
      "   at Submission#26.<<Initialize>>d__0.MoveNext()\r\n",
      "--- End of stack trace from previous location ---\r\n",
      "   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)"
     ]
    }
   ],
   "source": [
    "// 如果想要使用不是自己程序集中的内容,需要先加载程序集. eg:dll文件\n",
    "\n",
    "//三种加载程序集的函数\n",
    "//1. 一般用来加载同一个文件下的其他程序集\n",
    "//Assembly assembly = Assembly.Load(\"程序集名称\");\n",
    "//2. 一般用来加载不在同一个文件夹下的其他程序集\n",
    "//Assembly assembly = Assembly.LoadFrom(\"包含程序集清单的文件名称或路径\")\n",
    "//Assembly assembly = Assembly.LoadFile(\"要加载的文件的完全限定路径\")\n",
    "//LoadFrom和LoadFile使用方式与作用相同\n",
    "\n",
    "//先加载指定一个程序集\n",
    "Assembly assembly = Assembly.LoadFrom(@\"D:\\CSharpCode\\21.反射\\test.dll\");\n",
    "//得到程序集的类型信息\n",
    "Type[] types = assembly.GetTypes();\n",
    "for(int i = 0; i< types.Length; i++) {\n",
    "    Console.WriteLine(types[i]);\n",
    "    //打印types[i]类的具体信息\n",
    "    MemberInfo[] members = types[i].GetMembers();\n",
    "    for(int j = 0; j< members.Length; j++)  {\n",
    "        Console.WriteLine(members[j]);\n",
    "    }\n",
    "    //实例化一个对象\n",
    "    object obj = Activator.CreateInstance(types[i]);\n",
    "    \n",
    "    //调用方法\n",
    "    MethodInfo move = types[i].GetMethod(\"Move\");\n",
    "\n",
    "    move.Invoke(obj,null); //Move方法没有参数 \n",
    "    Console.WriteLine(\"==============================\");\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
